package nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;

/**
 * Instruction：
 * Author：@author MaLi
 */
public class NioSocketServer implements Runnable {
    private Selector selector;

    public NioSocketServer() {

        try {
            //创建选择器
            selector = Selector.open();
            //创建SocketServerChannel
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //配置Channel
            serverSocketChannel.bind(new InetSocketAddress(8888));
            serverSocketChannel.configureBlocking(false);
            //注册channel
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void run() {
        while (!Thread.interrupted()) {
            try {
                //选择器开始工作 - 在此阻塞
                selector.select();
                //接收客户端连接事件
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                //根据不同的事件, 选择不同的处理Handler
                for (SelectionKey selectionKey : selectionKeys) {
                    // 及时删除该事件, 否则无限循环处理.
                    selectionKeys.remove(selectionKey);
                    //连接事件
                    if (selectionKey.isAcceptable()) {
                        //获取到请求连接或者读就绪的的Channel
                        ServerSocketChannel socket = (ServerSocketChannel) selectionKey.channel();
                        SocketChannel socketChannel = socket.accept();
                        //配置该channel
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        System.out.println("连接阶段: 创建和配置好了一个socketChannel..等待传输数据");
                    }
                    //读就绪事件
                    if (selectionKey.isReadable()) {
                        //获取到请求连接或者读就绪的的Channel
                        SocketChannel socket = (SocketChannel) selectionKey.channel();
                        //创建Buffer
                        ByteBuffer buffer = ByteBuffer.allocate(8192);
                        //读取数据, 写入到buffer
                        int length = socket.read(buffer);
                        if (length > 0) {
                            System.out.println("服务端接收数据: "+new String(buffer.array(),length));
                            // print提示信息
                            System.out.println(new String("服务端数据发送..."));
                            // 写入数据到buffer
                            //buffer.put("消息已经收到".getBytes("utf-8"));
                            //buffer.flip();
                            // 发送给客户端
                            ByteBuffer response = ByteBuffer.allocate(1024);
                            response.put("end\r\n".getBytes());
                            response.flip();
                            socket.write(response);
                        }else if (length < 0) {
                            //数据已经传输完毕, 关掉该channel
                            selectionKey.cancel();
                            System.out.println("数据传输完毕...Channel已经关闭.");
                        }
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        //创建并启动服务端
        NioSocketServer server = new NioSocketServer();
        server.run();
    }
}
